package com.example.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.example.dao.OrderDao;
import com.example.dao.TreeDao;
import com.example.dao.UserDao;
import com.example.entity.*;
import com.example.exception.CustomException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;


@Service
public class OrderService {

    @Resource
    private OrderDao orderDao;

    @Resource
    private TreeDao treeDao;

    @Resource
    private UserDao userDao;

    @Resource
    private EmailService emailService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    //准备订单所需的所有信息 然后添加到数据库的order表中===================================
    public void addOrder(Integer treenumber,Integer treeId) {
        //1. 生成订单编号
        String code = RandomUtil.randomNumbers(14);
        //2. 得到订单生成时间
        String time = DateUtil.now();
        //3. 通过treeId拿到该树苗的信息
        TreeAndTreeName treeinfo = treeDao.findById(treeId);
        //4. 通过redis存储拿到userid并找到对应的登录用户信息
        String userId = redisTemplate.opsForValue().get("userid");
        User user = userDao.selectById(Integer.parseInt(userId));
        //5. 树苗总价
        int treeMoney = treeinfo.getTreeprice() * treenumber;
        //6. 获取用户身份 如果为普通用户则是购买订单 商家则是交换订单
        int ordertype = -1;
        int orderstatus = -1;
        if (user.getIdentity() == 1) {
            //普通用户则订单类型为购买订单(0)
            ordertype = 0;
            orderstatus = 0;

        } else if (user.getIdentity() == 2){
            //商家的交换订单信息(1)
            ordertype = 1;
            orderstatus = 7;
        }
        //6. 生成用户的购买订单信息或者是商家的交换订单信息
        Order order = new Order(null,code,treeinfo.getTreename(),treenumber,user.getUsername(),treeinfo.getUsername(),time,treeMoney,ordertype,orderstatus);
        //7. 添加订单信息
        orderDao.addOrder(order);
        //订单添加完成后 首先检查用户余额
        int userCoin = user.getCoin();
        if (userCoin >= treeMoney) {
            //余额够支付则扣除
            userDao.updatecoin(user.getUserId(),treeMoney);
            //扣除后 再对商家树苗的在售数量进行修改 需要的参数有treeId & treenumber
            //由于前端进行了数量的判断 所以在进行下单时不可能有树苗数量不够的情况 那么只需要考虑变为0的情况 变为0时从tree表中删除树苗记录
            treeDao.updatetree(treeId,treenumber);
            if (treeDao.findById(treeId).getSellnum() == 0){
                treeDao.deleteById(treeId);
            }
        } else {
            throw new CustomException("用户余额不足!");
        }
        //通过邮箱发送一封邮件说明用户完成一次订单
        emailService.sendSimpleMail(user.getEmail(), "您在树苗易售管理系统中发起了一次订单","订单编号:"+code + "\n本次订单金额:" + treeMoney +"元");
    }

    public PageInfo<OrderAndStatus> loadOrder(Integer userId,Params params) {
        //获取用户信息
        User user = userDao.selectById(userId);
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        //接下来的查询会按照当前的分页设置自动进行查询
        List<OrderAndStatus> list = orderDao.loadOrder(user.getUsername(),params);
        return PageInfo.of(list);
    }

    public PageInfo<OrderAndStatus> loadChangeOrder(Params params) {
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        //接下来的查询会按照当前的分页设置自动进行查询
        List<OrderAndStatus> list = orderDao.loadChangeOrder(params);
        return PageInfo.of(list);
    }

    //商家确认订单 需要对数据库的order表进行修改 然后发送邮件给用户 订单已完成
    public void checkOrder(Integer orderId) {
        //1. 获取所需的数据
        //获取订单信息
        Order orderinfo = orderDao.findByOrderId(orderId);
        //获取用户信息
        User userinfo = userDao.findByUsername(orderinfo.getUsername());
        //2. 修改order表
        int orderStatus = 1;
        orderDao.updateStatus(orderId,orderStatus);
        //3. 发送邮件
        emailService.sendSimpleMail(userinfo.getEmail(),"您的订单商家已确认","订单编号:" + orderinfo.getOrderCode());
    }

    //用户取消订单
    public void cancelOrder(Integer orderId) {
        //1. 获取信息
        //获取订单信息
        Order orderinfo = orderDao.findByOrderId(orderId);
        //获取商家信息
        User userinfo = userDao.findByUsername(orderinfo.getUsername());
        //2. 修改order表
        int orderStatus = 3;
        orderDao.updateStatus(orderId,orderStatus);
        //3. 发送邮件通知商家
        emailService.sendSimpleMail(userinfo.getEmail(),"您有一个订单等待取消","订单编号：" + orderinfo.getOrderCode());
    }

    //商家确认取消订单
    public void checkCancel(Integer orderId) {

        //1. 获取所需信息
        //获取订单信息
        Order orderinfo = orderDao.findByOrderId(orderId);
        //获取用户信息
        User userinfo = userDao.findByUsername(orderinfo.getUsername());
        //2. 返还用户余额
        userDao.backUserCoin(userinfo.getUserId(),orderinfo.getSummoney());
        //3. 修改order表信息
        int orderStatus = -1;
        orderDao.updateStatus(orderId,orderStatus);
        //4. 发送邮件通知用户订单取消成功
        emailService.sendSimpleMail(userinfo.getEmail(), "订单取消已完成，请前往查看","订单编号：" + orderinfo.getOrderCode()+ "\n订单总金额：" + orderinfo.getSummoney() + "元");
    }

    //用户确认收货
    public void confirmHarvest(Integer orderId) {
        //1. 获取所需信息
        //获取订单信息
        Order orderinfo = orderDao.findByOrderId(orderId);
        //获取用户信息
        User userinfo = userDao.findByUsername(orderinfo.getUsername());
        //获取商家信息
        User shopperinfo = userDao.findByUsername(orderinfo.getShopper());
        //2. 修改order表信息
        int orderStatus = 2;
        orderDao.updateStatus(orderId,orderStatus);
        //3. 修改用户和商家的信息
        //用户的余额已经在下单时修改了 所以不用修改
        //商家余额则需要加上该笔订单的金额
        userDao.backUserCoin(shopperinfo.getUserId(),orderinfo.getSummoney());
        //4. 发送邮件通知用户和商家订单完成
        emailService.sendSimpleMail(userinfo.getEmail(), "订单已完成","订单编号:" + orderinfo.getOrderCode() + "\n该次订单金额：" + orderinfo.getSummoney() + "元");
        emailService.sendSimpleMail(shopperinfo.getEmail(), "您有一笔订单完成","订单编号：" + orderinfo.getOrderCode() + "\n订单金额:" + orderinfo.getSummoney() + "元");

    }

    public PageInfo<OrderAndStatus> selectUserOrder(Params params) {
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        List<OrderAndStatus> list = orderDao.selectUserOrder(params);
        return PageInfo.of(list);
    }

    public PageInfo<OrderAndStatus> selectChangeOrder(Params params) {
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        List<OrderAndStatus> list = orderDao.selectChangeOrder(params);
        return PageInfo.of(list);
    }

    //将用户评价的评分信息写入数据库
    public void addEvaluate(Evaluate evaluate,Integer userId) {
        //在添加评分之前 要先做判断
        //如果该用户没有任何的订单信息 则不能进行售后服务
        List<String> code = orderDao.findOrderCodeByUserId(userId);
        if (code == null) {
            throw new CustomException("您还没有购买过任何树苗,不能参与售后服务");
        }
        //如果有订单信息 则需要先进行判断订单编号是否正确 需要将前端获取到的code与后端查询到的codelist进行比对
        else {
            int count = 0;
            for (String item: code) {
                //判断订单编号是否正确
                if (!evaluate.getOrderCode().equals(item)) {
                    //不正确则继续比对
                    count += 1;
                } else {
                    //正确则再判断是否参与过售后服务
                    Evaluate temp = orderDao.findEvaluateByOrderCode(item);
                    if (temp == null) {
                        //在评分表中没找到对应的订单编号 则正常进行售后服务
                        Evaluate evaluateInfo = new Evaluate(null,userId,evaluate.getOrderCode(),evaluate.getCheckSpeed(),evaluate.getOrderPrice(),evaluate.getUserMeet(),evaluate.getTreeQuality(),evaluate.getGuideService(),null,0);
                        orderDao.addEvaluate(evaluateInfo);
                    } else {
                        throw new CustomException("该笔订单已进行过商家服务评分");
                    }
                }

            }
            if (count == code.size()) {
                throw new CustomException("订单编号不正确或者订单不存在");
            }
        }
    }

    //售后服务的用户建议部分
    public void userSuggestion(Evaluate evaluate,Integer userId) {
        //先进行用户评价检测
        //确定有没有订单记录
        Evaluate tempEvaluate = orderDao.findEvaluateByOrderCode(evaluate.getOrderCode());
        if (tempEvaluate.getOrderCode() == null) {
            orderDao.addEvaluate(evaluate);
        } else {
            orderDao.updateEvaluate(evaluate);
        }
    }

    //查询用户反馈信息
    public PageInfo<EvaluateAndStatus> findeEvaluate(Params params,Integer userId) {
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        List<EvaluateAndStatus> list = orderDao.findeEvaluate(params,userId);
        return PageInfo.of(list);
    }

    //用户页面我的反馈取消操作
    public void cancelEvaluate(Integer evaluateId) {
        orderDao.cancelEvaluate(evaluateId);
    }

    //商家用户反馈信息
    public PageInfo<EvaluateAndStatus> findUserEvaluate(Params params, Integer userId) {

        //通过userId找到user信息(商家信息)
        User shopper = userDao.selectById(userId);
        // 通过userId表拿到所有orderCode;
        List<String> codelist = orderDao.findOrderCodeByShopper(shopper.getUsername());
        List<EvaluateAndStatus> info = new ArrayList<>();
        //通过orderCode在Evaluate表中检索信息
        for (String item : codelist) {
            Evaluate evaluateInfo = orderDao.findEvaluateByOrderCode(item);
            if (evaluateInfo == null) {
                //评价表中没有信息 说明该此订单未进行评价 啥也不干
            } else {
                info = orderDao.findEvaluateAndStatus(params,evaluateInfo.getUserId());

            }
        }
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        return PageInfo.of(info);
    }

    //商家确认反馈信息
    public void confirmInfo(Integer evaluateId) {
        orderDao.confirmInfo(evaluateId);
    }

    //管理员提醒商家确认用户反馈信息 通过邮箱提醒商家
    public void remindBusiness(Integer evaluateId) {
        //获取评价信息
         Evaluate evaluate = orderDao.findeEvaluateByEvaluateId(evaluateId);
         //通过orderCode找到商家名称
         String shopper = orderDao.findShopperByorderCode(evaluate.getOrderCode());
         //通过商家名称找到对应的邮箱信息
        String email = userDao.findByUsername(shopper).getEmail();
        emailService.sendSimpleMail(email,"来自管理员提醒","您有用户反馈信息未确认，请前往确认!" + "\n订单编号为:" + evaluate.getOrderCode());
    }

    //管理员的用户反馈信息页面
    public PageInfo<EvaluateAndStatus> findAllUserEvaluate(Params params) {
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        List<EvaluateAndStatus> list = orderDao.findAllUserEvaluate(params);
        return PageInfo.of(list);
    }

    //商家交换订单取消操作
    public void cancelChange(Integer orderId) {
        String orderCode = orderDao.findOrderCodeByOrderId(orderId);
        //删除订单表中的记录
        orderDao.cancelChange(orderId);
        //删除交换树苗表中的记录
        orderDao.delChangeTreeByOrderCode(orderCode);

    }

    //商家交换树苗确认收货操作
    public void confirmchangetree(Integer orderId, User user) {
        //
    }

    //商家添加交换订单信息
    public void addBusinessOrder(Integer treenumber, String item, String orderCode) {
        //拿到左边表单的树苗id treeId
        int treeId = ((Map<String,Integer>)JSON.parse(item)).get("treeId");
        //获取左边树苗信息
        Tree leftTree = treeDao.findTreeByTreeId(treeId);
        //拿到右边的form表单数据
        Map<String, Object> form = (Map<String, Object>) ((Map<?, ?>) JSON.parse(item)).get("form");
        //获取用于交换的树苗的信息 拿到右边总价
        int sumMoney = (int) form.get("righttreesum");
        //获取用于交换的树苗数量
        int number = (int) form.get("righttreenumber");
        //获取用于交换的树苗名称
        String treename = (String) form.get("righttreename");
        //通过Redis得到当前登录用户的userId 然后通过树苗名称和用户名称找到树苗id
        Integer userId = Integer.parseInt(redisTemplate.opsForValue().get("userid"));
        //获取商家(买家)名称
        String username = userDao.selectById(userId).getUsername();
        //获取右边树苗id
        Integer rightTreeId = treeDao.findTreeIdByUsernameAndTreeName(username,treename);
        //获取右边的树苗单价
        Integer rightTreePrice = (Integer) form.get("righttreeprice");
        ChangeTree changeTree = new ChangeTree(null,orderCode,rightTreeId,number,sumMoney,rightTreePrice);
        //添加树苗信息信到交换树苗表
        treeDao.addChangeTree(changeTree);
        //获得订单生成时间
        String  orderTime = DateUtil.now();
        //添加订单信息表数据order
        Order orderInfo = new Order(null,orderCode,leftTree.getTreename(),treenumber,username,leftTree.getUsername(),orderTime,sumMoney,1,7);
        orderDao.addOrder(orderInfo);
        //邮箱通知接收方商家确认交换信息
        User shopper = userDao.findShopperByUsername(leftTree.getUsername());
        emailService.sendSimpleMail(shopper.getEmail(),"您有一笔新的交换订单",
                "订单编号：" + orderCode +
                        "\n对方用于交换的树苗：" + treename +
                        "\n对方用于交换的数量：" + number +
                        "\n该笔订单的总金额为：" + sumMoney);
    }

    //商家等价交换操作
    public void equalPrice(String orderCode) {
        orderDao.equalPrice(orderCode);
    }

    //商家差额交换操作
    public void notEqual(String orderCode) {
        orderDao.notEqual(orderCode);
    }

    //发起方商家确认等价交换订单操作
    public void confirmEqualOrder(String orderCode) {
        orderDao.confirmEqualOrder(orderCode);
    }
    //发起方商家确认差额交换订单操作
    public void confirmNotEqualOrder(String orderCode) {
        orderDao.confirmNotEqualOrder(orderCode);
    }


    //接收方商家确认等价交换订单操作
    public void reconfirmEqualOrder(String orderCode) {
        orderDao.reconfirmEqualOrder(orderCode);
    }

    //接收方商家确认差额交换订单操作
    public void reconfirmNotEqualOrder(String orderCode) {
        orderDao.reconfirmNotEqualOrder(orderCode);
    }

    //发起方时间确认收货操作
    public void confirmTree(String orderCode) {
        //确认收货需要进行
    }

    //发起方商家收货操作  等价交换
    public void confirmEqualTree(String orderCode) {
        //获取数据
        //1. 获取接收方商家的被交换树苗信息
        Order orderinfo = orderDao.findByOrderCode(orderCode);
        int treeId = treeDao.findTreeIdByUsernameAndTreeName(orderinfo.getShopper(), orderinfo.getTreename());
        Tree tree = treeDao.findTreeByTreeId(treeId);
        System.out.println("接收方商家的被交换的树苗信息 = " + tree);
        System.out.println("交换的数量 = " + orderinfo.getNumber());
        //2. 获取发起方商家用于交换的树苗信息
        ChangeTree changeTree = treeDao.findChangeTreeByOrderCode(orderCode);
        Tree treeinfo = treeDao.findTreeByTreeId(changeTree.getTreeId());
        System.out.println("发起方商家用于交换的树苗信息 = " + treeinfo);
        System.out.println("用于交换的树苗的数量 = " + changeTree.getNumber());
        //3. 获取发起方商家数据
        User user = userDao.findByUsername(orderinfo.getUsername());
        System.out.println("发起方商家信息 = " + user);
        //4. 获取接收方商家信息
        User shopper = userDao.findByUsername(orderinfo.getShopper());
        System.out.println("接收方商家信息 = " + shopper);
        //5. 判断用户的余额
        //接收方的树苗总金额
        int shopperSumMoney = orderinfo.getNumber() * tree.getTreeprice();
        System.out.println("接收方的树苗总价 = " + shopperSumMoney);
        //发起方树苗总金额
        int userSumMoney = treeinfo.getTreeprice() * changeTree.getNumber();
        System.out.println("发起方的树苗总价 = " + userSumMoney);
        int coin = 0;
        if (userSumMoney >= shopperSumMoney) {
            //发起方价高 则接收方补差价
            coin = userSumMoney-shopperSumMoney;
            if (shopper.getCoin() >= coin) {
                //商家余额充足则修改信息
                //修改发起方商家信息和树苗信息
                userDao.updateCoin(user.getUserId(), coin);
                Tree treeInfo = treeDao.findTreeByUsernameAndTreeName(user.getUsername(), tree.getTreename());
                if (treeInfo == null) {
                    tree.setTreeId(null);
                    tree.setSellnum(orderinfo.getNumber());
                    tree.setUsername(user.getUsername());
                    treeDao.addTree(tree);
                } else {
                    treeDao.updateTree(treeDao.findTreeIdByUsernameAndTreeName(user.getUsername(),tree.getTreename()),treeDao.findTreeByUsernameAndTreeName(user.getUsername(),tree.getTreename()).getSellnum() + orderinfo.getNumber());
                }
                //修改接收方商家信息和树苗信息
                userDao.updatecoin(shopper.getUserId(),coin);
                treeInfo = treeDao.findTreeByUsernameAndTreeName(shopper.getUsername(), treeInfo.getTreename());
                if (treeInfo == null) {
                    //没有则新增
                    treeInfo.setTreeId(null);
                    treeInfo.setUsername(shopper.getUsername());
                    treeInfo.setSellnum(changeTree.getNumber());
                    treeDao.addTree(treeInfo);
                } else {
                    //有就修改数量
                    treeDao.updateTree(treeDao.findTreeIdByUsernameAndTreeName(shopper.getUsername(), treeinfo.getTreename()),treeDao.findTreeByUsernameAndTreeName(shopper.getUsername(), treeinfo.getTreename()).getSellnum() + changeTree.getNumber());
                }
            } else {
                throw new CustomException("接收方商家用户余额不足");
            }
        } else {
            //发起方价低
            coin = shopperSumMoney - userSumMoney;
            if (user.getCoin() >= coin) {
                //发起方商家余额充足则修改信息
                //修改发起方商家信息和树苗信息
                userDao.updatecoin(user.getUserId(), coin);
                Tree treeInfo = treeDao.findTreeByUsernameAndTreeName(user.getUsername(), tree.getTreename());
                if (treeInfo == null) {
                    tree.setTreeId(null);
                    tree.setSellnum(orderinfo.getNumber());
                    tree.setUsername(user.getUsername());
                    treeDao.addTree(tree);
                } else {
                    treeDao.updateTree(treeDao.findTreeIdByUsernameAndTreeName(user.getUsername(),tree.getTreename()),treeDao.findTreeByUsernameAndTreeName(user.getUsername(),tree.getTreename()).getSellnum() + orderinfo.getNumber());
                }
                //修改接收方商家信息和树苗信息
                userDao.updateCoin(shopper.getUserId(),coin);
                treeInfo = treeDao.findTreeByUsernameAndTreeName(shopper.getUsername(), treeInfo.getTreename());
                if (treeInfo == null) {
                    //没有则新增
                    treeInfo.setTreeId(null);
                    treeInfo.setUsername(shopper.getUsername());
                    treeInfo.setSellnum(changeTree.getNumber());
                    treeDao.addTree(treeInfo);
                } else {
                    //有就修改数量
                    treeDao.updateTree(treeDao.findTreeIdByUsernameAndTreeName(shopper.getUsername(), treeinfo.getTreename()),treeDao.findTreeByUsernameAndTreeName(shopper.getUsername(), treeinfo.getTreename()).getSellnum() + changeTree.getNumber());
                }
            } else {
                throw new CustomException("接收方商家用户余额不足");
            }
        }
        int orderId = orderDao.findorderIdByorderCode(orderCode);
        orderDao.updateStatus(orderId,2);
    }
}
